package database

import (
	"context"
	"dustbe/util"
	"fmt"
	"strings"

	"github.com/neo4j/neo4j-go-driver/v5/neo4j"
)

type Neo4jTuple struct {
	FirstNode *neo4j.Node
	Relationship *neo4j.Relationship
	SecondNode *neo4j.Node
}

func makeNeo4jTuple(neo4jQuery neo4j.ResultWithContext, firstNodeName, relationshipName, secondNodeName string) []Neo4jTuple {
	queryTuples := make([]Neo4jTuple, 0)
	
	for neo4jQuery.Next(context.TODO()) {
		n, _ := neo4jQuery.Record().Get(firstNodeName)
		r, _ := neo4jQuery.Record().Get(relationshipName)
		m, _ := neo4jQuery.Record().Get(secondNodeName)
		var tuple Neo4jTuple
		firstNode := n.(neo4j.Node)
		relationship := r.(neo4j.Relationship)
		secondNode := m.(neo4j.Node)

		tuple.FirstNode = &firstNode
		tuple.Relationship = &relationship
		tuple.SecondNode = &secondNode
		queryTuples = append(queryTuples, tuple)
	}
	return queryTuples
}

// names是用逗号隔开的事件组，比如world,war
func SearchByEventName(namesString string, limit int) ([]Neo4jTuple, error) {
	names := strings.Split(namesString, ",")
	reg := util.GetNeo4jRegSearchString(names)
	cypher := fmt.Sprintf("match (n:EVENT) where n.name=%s with n match (n)-[r]-(m) return n,r,m limit %d",
					reg, limit)
	session := Neo4jDriver.NewSession(neo4j.SessionConfig{
		AccessMode: neo4j.AccessModeRead,
	})
	defer session.Close(context.TODO())

	result, err := session.Run(context.TODO(), cypher, nil)
	if err != nil {
		fmt.Println(err.Error())
		return nil, err
	}

	queryTuples := makeNeo4jTuple(result, "n", "r", "m")
	return queryTuples, nil
}


// 给出两个节点的关键词，寻找这两个节点的关系
func SearchByTwoEventNames(startText, endText string, limit int) ([]Neo4jTuple, error) {
	startNames := strings.Split(startText, ",")
	endNames := strings.Split(endText, ",")
	startReg := util.GetNeo4jRegSearchString(startNames)
	endReg := util.GetNeo4jRegSearchString(endNames)

	cypher := fmt.Sprintf("match (n:EVENT)-[r]-(m:EVENT) where n.name=%s and m.name=%s return n,r,m limit %d",
				startReg, endReg, limit)
	
	session := Neo4jDriver.NewSession(neo4j.SessionConfig{
		AccessMode: neo4j.AccessModeRead,
	})
	defer session.Close(context.TODO())

	result, err := session.Run(context.TODO(), cypher, nil)
	if err != nil {
		fmt.Println(err.Error())
		return nil, err
	}

	queryTuples := makeNeo4jTuple(result, "n", "r", "m")
	return queryTuples, nil
}